import numpy as np
from numba import types
from numba.pycc import CC

# Create compiler object
cc = CC('compiled_cloud_mesh')


@cc.export('generate_cloud_mesh',
           types.Tuple((types.float32[:], types.uint32[:]))(
               types.float32[:],  # center_pos (x, y)
               types.int32,  # radius
               types.float32[:, :],  # face_vertices (24x6 array)
               types.uint8[:, :]  # clouds_layout (256x256 array)
           ))
def generate_cloud_mesh(center_pos, radius, face_vertices, clouds_layout):
    min_x = int(center_pos[0] - radius)
    min_y = int(center_pos[1] - radius)
    max_x = int(center_pos[0] + radius)
    max_y = int(center_pos[1] + radius)

    # Calculate maximum possible vertices and indices
    max_vertices = (radius * 2) * (radius * 2) * 6 * 4  # More conservative estimate
    vertices = np.empty(max_vertices * 6, dtype=np.float32)  # 6 values per vertex
    indices = np.empty(max_vertices * 6 // 4, dtype=np.uint32)  # 6 indices per quad
    vertex_count = 0
    index_count = 0
    index = 0

    for x in range(min_x, max_x):
        for y in range(min_y, max_y):
            l = clouds_layout[x & 0xff, y & 0xff]
            if l == 0:
                continue

            dx = x - center_pos[0]
            dy = y - center_pos[1]

            # Face 1 (top)
            start = 4 * 4
            for i in range(4):
                offset = vertex_count + i * 6
                vertices[offset + 0] = face_vertices[start + i, 0] + dx
                vertices[offset + 1] = face_vertices[start + i, 1]
                vertices[offset + 2] = face_vertices[start + i, 2] + dy
                vertices[offset + 3] = face_vertices[start + i, 3]
                vertices[offset + 4] = face_vertices[start + i, 4]
                vertices[offset + 5] = face_vertices[start + i, 5]
            vertex_count += 24  # 4 vertices * 6 attributes
            indices[index_count:index_count + 6] = [index, index + 1, index + 2, index, index + 2, index + 3]
            index_count += 6
            index += 4

            # Face 2 (bottom)
            start = 4 * 5
            for i in range(4):
                offset = vertex_count + i * 6
                vertices[offset + 0] = face_vertices[start + i, 0] + dx
                vertices[offset + 1] = face_vertices[start + i, 1]
                vertices[offset + 2] = face_vertices[start + i, 2] + dy
                vertices[offset + 3] = face_vertices[start + i, 3]
                vertices[offset + 4] = face_vertices[start + i, 4]
                vertices[offset + 5] = face_vertices[start + i, 5]
            vertex_count += 24
            indices[index_count:index_count + 6] = [index, index + 1, index + 2, index, index + 2, index + 3]
            index_count += 6
            index += 4

            # Side faces (check neighbors)
            # Left face
            if clouds_layout[(x - 1) & 0xff, y & 0xff] == 0:
                start = 4 * 2
                for i in range(4):
                    offset = vertex_count + i * 6
                    vertices[offset + 0] = face_vertices[start + i, 0] + dx
                    vertices[offset + 1] = face_vertices[start + i, 1]
                    vertices[offset + 2] = face_vertices[start + i, 2] + dy
                    vertices[offset + 3] = face_vertices[start + i, 3]
                    vertices[offset + 4] = face_vertices[start + i, 4]
                    vertices[offset + 5] = face_vertices[start + i, 5]
                vertex_count += 24
                indices[index_count:index_count + 6] = [index, index + 1, index + 2, index, index + 2, index + 3]
                index_count += 6
                index += 4

            # Right face
            if clouds_layout[(x + 1) & 0xff, y & 0xff] == 0:
                start = 4 * 3
                for i in range(4):
                    offset = vertex_count + i * 6
                    vertices[offset + 0] = face_vertices[start + i, 0] + dx
                    vertices[offset + 1] = face_vertices[start + i, 1]
                    vertices[offset + 2] = face_vertices[start + i, 2] + dy
                    vertices[offset + 3] = face_vertices[start + i, 3]
                    vertices[offset + 4] = face_vertices[start + i, 4]
                    vertices[offset + 5] = face_vertices[start + i, 5]
                vertex_count += 24
                indices[index_count:index_count + 6] = [index, index + 1, index + 2, index, index + 2, index + 3]
                index_count += 6
                index += 4

            # Up face
            if clouds_layout[x & 0xff, (y + 1) & 0xff] == 0:
                start = 4 * 0
                for i in range(4):
                    offset = vertex_count + i * 6
                    vertices[offset + 0] = face_vertices[start + i, 0] + dx
                    vertices[offset + 1] = face_vertices[start + i, 1]
                    vertices[offset + 2] = face_vertices[start + i, 2] + dy
                    vertices[offset + 3] = face_vertices[start + i, 3]
                    vertices[offset + 4] = face_vertices[start + i, 4]
                    vertices[offset + 5] = face_vertices[start + i, 5]
                vertex_count += 24
                indices[index_count:index_count + 6] = [index, index + 1, index + 2, index, index + 2, index + 3]
                index_count += 6
                index += 4

            # Down face
            if clouds_layout[x & 0xff, (y - 1) & 0xff] == 0:
                start = 4 * 1
                for i in range(4):
                    offset = vertex_count + i * 6
                    vertices[offset + 0] = face_vertices[start + i, 0] + dx
                    vertices[offset + 1] = face_vertices[start + i, 1]
                    vertices[offset + 2] = face_vertices[start + i, 2] + dy
                    vertices[offset + 3] = face_vertices[start + i, 3]
                    vertices[offset + 4] = face_vertices[start + i, 4]
                    vertices[offset + 5] = face_vertices[start + i, 5]
                vertex_count += 24
                indices[index_count:index_count + 6] = [index, index + 1, index + 2, index, index + 2, index + 3]
                index_count += 6
                index += 4

    return vertices[:vertex_count], indices[:index_count]

if __name__ == "__main__":
    cc.compile()